// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "WorldEntityPart.h"
#include "WorldContactPoint.h"
#include "WorldRoadKind.h"
#include "WorldSpeedUnit.h"
#include "WorldPPolyParameterRange.h"
#include "WorldCrossfallSide.h"
#include "WorldLaneType.h"
#include "WorldRoadMarkKind.h"
#include "WorldRoadMarkWeight.h"
#include "WorldRoadMarkColor.h"
#include "WorldLaneChange.h"
#include "WorldRoadMarkLineRule.h"
#include "WorldLaneRestrictionType.h"
#include "WorldRoadObjectOrientation.h"
#include "WorldLaneValidity.h"

class FWorldConnectable;
class FWorldRoadObject;
class FWorldTunnel;
class FWorldBridge;
class FWorldSignal;

/**
 * An entity of a road/surface/CRG
 */
class FWorldRoadSurfaceCRG : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadSurfaceCRG>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< std::string >		File;
	FWorldEntityProperty< double >			SStart;
	FWorldEntityProperty< double >			SEnd;
	FWorldEntityProperty< std::string >		Orientation;
	FWorldEntityProperty< std::string >		Mode;
	FWorldEntityProperty< std::string >		Purpose;
	FWorldEntityProperty< double >			SOffset;
	FWorldEntityProperty< double >			TOffset;
	FWorldEntityProperty< double >			ZOffset;
	FWorldEntityProperty< double >			ZScale;
	FWorldEntityProperty< double >			HOffset;

public:

	FWorldRoadSurfaceCRG();
	FWorldRoadSurfaceCRG(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadSurfaceCRG() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadSurfaceCRG)

};

/**
 * An entity of a road/surface
 */
class FWorldRoadSurface : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadSurface>;
	using Super = FWorldEntityPart;

	FWorldEntityPartArrayReference< FWorldRoadSurfaceCRG, 0, INT_MAX >	CRG;

public:

	FWorldRoadSurface();
	FWorldRoadSurface(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadSurface() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadSurface)

};

/**
 * An entity of a road/signals/signalReference
 */
class FWorldSignalReference : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldSignalReference>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >										S;
	FWorldEntityProperty< double >										T;
	FWorldEntityReference< FWorldSignal >								ID;
	FWorldEntityProperty< FWorldRoadObjectOrientation >					Orientation;
	FWorldEntityPartArrayReference< FWorldLaneValidity, 0, INT_MAX >	Validity;

public:

	FWorldSignalReference();
	FWorldSignalReference(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldSignalReference() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldSignalReference)

};

/**
 * An entity of a road/objects/signal (proxy)
 */
class FWorldSignalProxy : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldSignalProxy>;
	using Super = FWorldEntityPart;

	FWorldEntityReference< FWorldSignal >	ID;

public:

	FWorldSignalProxy();
	FWorldSignalProxy(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldSignalProxy() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldSignalProxy)

};

/**
 * An entity of a road/signals
 */
class FWorldRoadSignals : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadSignals>;
	using Super = FWorldEntityPart;

	FWorldEntityPartArrayReference< FWorldSignalProxy, 0, INT_MAX >		Signal;
	FWorldEntityPartArrayReference< FWorldSignalReference, 0, INT_MAX >	SignalReference;

public:

	FWorldRoadSignals();
	FWorldRoadSignals(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadSignals() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadSignals)

};

/**
 * An entity of a road/objects/bridge (proxy)
 */
class FWorldBridgeProxy : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldBridgeProxy>;
	using Super = FWorldEntityPart;

	FWorldEntityReference< FWorldBridge >	ID;

public:

	FWorldBridgeProxy();
	FWorldBridgeProxy(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldBridgeProxy() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldBridgeProxy)

};

/**
 * An entity of a road/objects/tunnel (proxy)
 */
class FWorldTunnelProxy : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldTunnelProxy>;
	using Super = FWorldEntityPart;

	FWorldEntityReference< FWorldTunnel >	ID;

public:

	FWorldTunnelProxy();
	FWorldTunnelProxy(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldTunnelProxy() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldTunnelProxy)

};

/**
 * An entity of a road/objects/objectReference
 */
class FWorldRoadObjectReference : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadObjectReference>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >										S;
	FWorldEntityProperty< double >										T;
	FWorldEntityReference< FWorldRoadObject >							ID;
	FWorldEntityProperty< double >										ZOffset;
	FWorldEntityProperty< double >										ValidLength;
	FWorldEntityProperty< FWorldRoadObjectOrientation >					Orientation;
	FWorldEntityPartArrayReference< FWorldLaneValidity, 0, INT_MAX >	Validity;

public:

	FWorldRoadObjectReference();
	FWorldRoadObjectReference(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadObjectReference() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadObjectReference)

};

/**
 * An entity of a road/objects/object (proxy)
 */
class FWorldRoadObjectProxy : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadObjectProxy>;
	using Super = FWorldEntityPart;

	FWorldEntityReference< FWorldRoadObject >	ID;

public:

	FWorldRoadObjectProxy();
	FWorldRoadObjectProxy(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadObjectProxy() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadObjectProxy)

};

/**
 * An entity of a road/objects
 */
class FWorldRoadObjects : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadObjects>;
	using Super = FWorldEntityPart;

	FWorldEntityPartArrayReference< FWorldRoadObjectProxy, 0, INT_MAX >		Object;
	FWorldEntityPartArrayReference< FWorldRoadObjectReference, 0, INT_MAX >	ObjectReference;
	FWorldEntityPartArrayReference< FWorldTunnelProxy, 0, INT_MAX >			Tunnel;
	FWorldEntityPartArrayReference< FWorldBridgeProxy, 0, INT_MAX >			Bridge;

public:

	FWorldRoadObjects();
	FWorldRoadObjects(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadObjects() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadObjects)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/height
 */
class FWorldLaneRule : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneRule>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >		SOffset;
	FWorldEntityProperty< std::string >	Value;

public:

	FWorldLaneRule();
	FWorldLaneRule(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneRule() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneRule)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/height
 */
class FWorldLaneHeight : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneHeight>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >	SOffset;
	FWorldEntityProperty< double >	Inner;
	FWorldEntityProperty< double >	Outer;

public:

	FWorldLaneHeight();
	FWorldLaneHeight(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneHeight() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneHeight)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/access
 */
class FWorldLaneAccess : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneAccess>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >						SOffset;
	FWorldEntityProperty< FWorldLaneRestrictionType >	Restriction;

public:

	FWorldLaneAccess();
	FWorldLaneAccess(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneAccess() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneAccess)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/speed
 */
class FWorldLaneSpeed : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneSpeed>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >			SOffset;
	FWorldEntitySpeedProperty				Max;
	FWorldEntityProperty< FWorldSpeedUnit >	Unit;

public:

	FWorldLaneSpeed();
	FWorldLaneSpeed(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneSpeed() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneSpeed)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/visibility
 */
class FWorldLaneVisibility : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneVisibility>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >	SOffset;
	FWorldEntityProperty< double >	Forward;
	FWorldEntityProperty< double >	Back;
	FWorldEntityProperty< double >	Left;
	FWorldEntityProperty< double >	Right;

public:

	FWorldLaneVisibility();
	FWorldLaneVisibility(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneVisibility() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneVisibility)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/material
 */
class FWorldLaneMaterial : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneMaterial>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >		SOffset;
	FWorldEntityProperty< std::string >	Surface;
	FWorldEntityProperty< double >		Friction;
	FWorldEntityProperty< double >		Roughness;

public:

	FWorldLaneMaterial();
	FWorldLaneMaterial(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneMaterial() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneMaterial)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/roadMark/type/line
 */
class FWorldRoadMarkTypeLine : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadMarkTypeLine>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >					Length;
	FWorldEntityProperty< double >					Space;
	FWorldEntityProperty< double >					TOffset;
	FWorldEntityProperty< double >					SOffset;
	FWorldEntityProperty< FWorldRoadMarkLineRule >	Rule;
	FWorldEntityProperty< double >					Width;

public:

	FWorldRoadMarkTypeLine();
	FWorldRoadMarkTypeLine(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadMarkTypeLine() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadMarkTypeLine)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/roadMark/type
 */
class FWorldRoadMarkType : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadMarkType>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< std::string >										Name;
	FWorldEntityProperty< double >											Width;
	FWorldEntityPartArrayReference< FWorldRoadMarkTypeLine, 1, INT_MAX >	Line;

public:

	FWorldRoadMarkType();
	FWorldRoadMarkType(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadMarkType() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadMarkType)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/roadMark
 */
class FWorldRoadMark : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadMark>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >						SOffset;
	FWorldEntityProperty< FWorldRoadMarkKind >			Type;
	FWorldEntityProperty< FWorldRoadMarkWeight >		Weight;
	FWorldEntityProperty< FWorldRoadMarkColor >			Color;
	FWorldEntityProperty< std::string >					Material;
	FWorldEntityProperty< double >						Width;
	FWorldEntityProperty< FWorldLaneChange >			LaneChange;
	FWorldEntityProperty< double >						Height;
	FWorldEntityPartReference< FWorldRoadMarkType, 0 >	TypeDef;

public:

	FWorldRoadMark();
	FWorldRoadMark(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadMark() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadMark)

};

/**
 * An entity of a road/lanes/laneSection/[left|right]/lane/border
 */
class FWorldLaneBorder : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneBorder>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >	SOffset;
	FWorldEntityProperty< double >	A;
	FWorldEntityProperty< double >	B;
	FWorldEntityProperty< double >	C;
	FWorldEntityProperty< double >	D;

public:

	FWorldLaneBorder();
	FWorldLaneBorder(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneBorder() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneBorder)

};

/**
 * An entity of a road/lanes/laneSection/[left|right]/lane/width
 */
class FWorldLaneWidth : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneWidth>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >	SOffset;
	FWorldEntityProperty< double >	A;
	FWorldEntityProperty< double >	B;
	FWorldEntityProperty< double >	C;
	FWorldEntityProperty< double >	D;

public:

	FWorldLaneWidth();
	FWorldLaneWidth(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneWidth() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneWidth)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/link/[predecessor|successor]
 */
class FWorldLaneConnector : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneConnector>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< int >	ID;

public:

	FWorldLaneConnector();
	FWorldLaneConnector(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneConnector() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneConnector)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane/link
 */
class FWorldLaneLink : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneLink>;
	using Super = FWorldEntityPart;

	FWorldEntityPartReference< FWorldLaneConnector, 0 >	Predecessor;
	FWorldEntityPartReference< FWorldLaneConnector, 0 >	Successor;

public:

	FWorldLaneLink();
	FWorldLaneLink(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneLink() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneLink)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]/lane
 */
class FWorldLane : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLane>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< int >											ID;
	FWorldEntityProperty< FWorldLaneType >								Type;
	FWorldEntityBoolProperty<FWorldEntityBoolTrueFalseRule>				Level;
	FWorldEntityPartReference< FWorldLaneLink, 0 >						Link;
	FWorldEntityPartArrayReference< FWorldLaneWidth, 0, INT_MAX >		Width;
	FWorldEntityPartArrayReference< FWorldLaneBorder, 0, INT_MAX >		Border;
	FWorldEntityPartArrayReference< FWorldRoadMark, 0, INT_MAX >		RoadMark;
	FWorldEntityPartArrayReference< FWorldLaneMaterial, 0, INT_MAX >	Material;
	FWorldEntityPartArrayReference< FWorldLaneVisibility, 0, INT_MAX >	Visibility;
	FWorldEntityPartArrayReference< FWorldLaneSpeed, 0, INT_MAX >		Speed;
	FWorldEntityPartArrayReference< FWorldLaneAccess, 0, INT_MAX >		Access;
	FWorldEntityPartArrayReference< FWorldLaneHeight, 0, INT_MAX >		Height;

public:

	FWorldLane();
	FWorldLane(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLane() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldLane)

};

/**
 * An entity of a road/lanes/laneSection/[left|center|right]
 */
class FWorldLaneGroup : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneGroup>;
	using Super = FWorldEntityPart;

	FWorldEntityPartArrayReference< FWorldLane, 1, INT_MAX >	Lane;

public:

	FWorldLaneGroup();
	FWorldLaneGroup(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneGroup() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneGroup)

};

/**
 * An entity of a road/lanes/laneSection
 */
class FWorldLaneSection : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneSection>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >								S;
	FWorldEntityBoolProperty< FWorldEntityBoolTrueFalseRule >	SingleSide;
	FWorldEntityPartReference< FWorldLaneGroup, 0 >				Left;
	FWorldEntityPartReference< FWorldLaneGroup, 0 >				Center;
	FWorldEntityPartReference< FWorldLaneGroup, 0 >				Right;

public:

	FWorldLaneSection();
	FWorldLaneSection(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneSection() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneSection)

};

/**
 * An entity of a road/lanes/laneOffset
 */
class FWorldLaneOffset : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLaneOffset>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >	S;
	FWorldEntityProperty< double >	A;
	FWorldEntityProperty< double >	B;
	FWorldEntityProperty< double >	C;
	FWorldEntityProperty< double >	D;

public:

	FWorldLaneOffset();
	FWorldLaneOffset(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLaneOffset() override;

	WORLD_ENTITY_META_DECLARE(FWorldLaneOffset)

};

/**
 * An entity of a road/lateralProfile/lanes
 */
class FWorldLanes : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldLanes>;
	using Super = FWorldEntityPart;

	FWorldEntityPartArrayReference< FWorldLaneOffset, 0, INT_MAX >	LaneOffset;
	FWorldEntityPartArrayReference< FWorldLaneSection, 1, INT_MAX >	LaneSection;

public:

	FWorldLanes();
	FWorldLanes(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldLanes() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldLanes)

};

/**
 * An entity of a road/lateralProfile/shape
 */
class FWorldRoadShape : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadShape>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >	S;
	FWorldEntityProperty< double >	T;
	FWorldEntityProperty< double >	A;
	FWorldEntityProperty< double >	B;
	FWorldEntityProperty< double >	C;
	FWorldEntityProperty< double >	D;

public:

	FWorldRoadShape();
	FWorldRoadShape(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadShape() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadShape)

};

/**
 * An entity of a road/lateralProfile/crossfall
 */
class FWorldRoadCrossfall : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadCrossfall>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< FWorldCrossfallSide >	Side;
	FWorldEntityProperty< double >				S;
	FWorldEntityProperty< double >				A;
	FWorldEntityProperty< double >				B;
	FWorldEntityProperty< double >				C;
	FWorldEntityProperty< double >				D;

public:

	FWorldRoadCrossfall();
	FWorldRoadCrossfall(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadCrossfall() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadCrossfall)

};

/**
 * An entity of a road/lateralProfile/superelevation
 */
class FWorldRoadSuperelevation : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadSuperelevation>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >	S;
	FWorldEntityProperty< double >	A;
	FWorldEntityProperty< double >	B;
	FWorldEntityProperty< double >	C;
	FWorldEntityProperty< double >	D;

public:

	FWorldRoadSuperelevation();
	FWorldRoadSuperelevation(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadSuperelevation() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadSuperelevation)

};

/**
 * An entity of a road/lateralProfile
 */
class FWorldRoadLateralProfile : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadLateralProfile>;
	using Super = FWorldEntityPart;

	FWorldEntityPartArrayReference< FWorldRoadSuperelevation, 0, INT_MAX >	Superelevation;
	FWorldEntityPartArrayReference< FWorldRoadCrossfall, 0, INT_MAX >		Crossfall;
	FWorldEntityPartArrayReference< FWorldRoadShape, 0, INT_MAX >			Shape;

public:

	FWorldRoadLateralProfile();
	FWorldRoadLateralProfile(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadLateralProfile() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadLateralProfile)

};

/**
 * An entity of a road/elevationProfile/elevation
 */
class FWorldRoadElevation : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadElevation>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >	S;
	FWorldEntityProperty< double >	A;
	FWorldEntityProperty< double >	B;
	FWorldEntityProperty< double >	C;
	FWorldEntityProperty< double >	D;

public:

	FWorldRoadElevation();
	FWorldRoadElevation(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadElevation() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadElevation)

};

/**
 * An entity of a road/elevationProfile
 */
class FWorldRoadElevationProfile : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadElevationProfile>;
	using Super = FWorldEntityPart;

	FWorldEntityPartArrayReference< FWorldRoadElevation, 1, INT_MAX >	Elevation;

public:

	FWorldRoadElevationProfile();
	FWorldRoadElevationProfile(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadElevationProfile() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadElevationProfile)

};

/**
 * An entity of a road/planView/geometry/[? extends base]
 */
class FWorldRoadGeometryBase : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadGeometryBase>;
	using Super = FWorldEntityPart;

public:

	FWorldRoadGeometryBase();
	FWorldRoadGeometryBase(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadGeometryBase() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadGeometryBase)

};

/**
 * An entity of a road/planView/geometry/paramPoly3
 */
class FWorldRoadGeometryPPoly3 : public FWorldRoadGeometryBase
{

public:

	using Ptr = std::shared_ptr<FWorldRoadGeometryPPoly3>;
	using Super = FWorldRoadGeometryBase;

	FWorldEntityProperty< double >						Au;
	FWorldEntityProperty< double >						Bu;
	FWorldEntityProperty< double >						Cu;
	FWorldEntityProperty< double >						Du;
	FWorldEntityProperty< double >						Av;
	FWorldEntityProperty< double >						Bv;
	FWorldEntityProperty< double >						Cv;
	FWorldEntityProperty< double >						Dv;
	FWorldEntityProperty< FWorldPPolyParameterRange >	Prange;

public:

	FWorldRoadGeometryPPoly3();
	FWorldRoadGeometryPPoly3(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadGeometryPPoly3() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadGeometryPPoly3)

};

/**
 * An entity of a road/planView/geometry/poly3
 */
class FWorldRoadGeometryPoly3 : public FWorldRoadGeometryBase
{

public:

	using Ptr = std::shared_ptr<FWorldRoadGeometryPoly3>;
	using Super = FWorldRoadGeometryBase;

	FWorldEntityProperty< double >	A;
	FWorldEntityProperty< double >	B;
	FWorldEntityProperty< double >	C;
	FWorldEntityProperty< double >	D;

public:

	FWorldRoadGeometryPoly3();
	FWorldRoadGeometryPoly3(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadGeometryPoly3() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadGeometryPoly3)

};

/**
 * An entity of a road/planView/geometry/spiral
 */
class FWorldRoadGeometrySpiral : public FWorldRoadGeometryBase
{

public:

	using Ptr = std::shared_ptr<FWorldRoadGeometrySpiral>;
	using Super = FWorldRoadGeometryBase;

	FWorldEntityProperty< double >	CurvStart;
	FWorldEntityProperty< double >	CurvEnd;

public:

	FWorldRoadGeometrySpiral();
	FWorldRoadGeometrySpiral(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadGeometrySpiral() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadGeometrySpiral)

};

/**
 * An entity of a road/planView/geometry/arc
 */
class FWorldRoadGeometryArc : public FWorldRoadGeometryBase
{

public:

	using Ptr = std::shared_ptr<FWorldRoadGeometryArc>;
	using Super = FWorldRoadGeometryBase;

	FWorldEntityProperty< double >	Curvature;

public:

	FWorldRoadGeometryArc();
	FWorldRoadGeometryArc(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadGeometryArc() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadGeometryArc)

};

/**
 * An entity of a road/planView/geometry/line
 */
class FWorldRoadGeometryLine : public FWorldRoadGeometryBase
{

public:

	using Ptr = std::shared_ptr<FWorldRoadGeometryLine>;
	using Super = FWorldRoadGeometryBase;

public:

	FWorldRoadGeometryLine();
	FWorldRoadGeometryLine(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadGeometryLine() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadGeometryLine)

};

/**
 * An entity of a road/planView/geometry
 */
class FWorldRoadGeometry : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadGeometry>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< double >							S;
	FWorldEntityProperty< double >							X;
	FWorldEntityProperty< double >							Y;
	FWorldEntityProperty< double >							Hdg;
	FWorldEntityProperty< double >							Length;
	FWorldEntityPartReference< FWorldRoadGeometryBase, 1 >	Variant;

public:

	FWorldRoadGeometry();
	FWorldRoadGeometry(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadGeometry() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadGeometry)

private:

	FWorldRoadGeometryBase::Ptr VariantFromXml(FWorldEntityPart* parent, const pugi::xml_node& elem);

};

/**
 * An entity of a road/planView
 */
class FWorldPlanView : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldPlanView>;
	using Super = FWorldEntityPart;

	FWorldEntityPartArrayReference<FWorldRoadGeometry, 1, INT_MAX>	Geometry;

public:

	FWorldPlanView();
	FWorldPlanView(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldPlanView() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldPlanView)

};

/**
 * An entity of a road/type/speed
 */
class FWorldRoadSpeed : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadSpeed>;
	using Super = FWorldEntityPart;

	FWorldEntitySpeedProperty				Max;
	FWorldEntityProperty< FWorldSpeedUnit >	Unit;

public:

	FWorldRoadSpeed();
	FWorldRoadSpeed(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadSpeed() override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadSpeed)

};

/**
 * An entity of a road/type
 */
class FWorldRoadType : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadType>;
	using Super = FWorldEntityPart;


	FWorldEntityProperty< double >					S;
	FWorldEntityProperty< FWorldRoadKind >			Type;
	FWorldEntityPartReference< FWorldRoadSpeed, 0 >	Speed;

public:

	FWorldRoadType();
	FWorldRoadType(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadType() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadType)

};

/**
 * An entity of a road/link/predecessor or road/link/successor.
 */
class FWorldConnector : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldConnector>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< std::string >			ElementType;
	FWorldEntityReference< FWorldConnectable >	ElementId;
	FWorldEntityProperty< FWorldContactPoint >	ContactPoint;

public:

	FWorldConnector();
	FWorldConnector(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldConnector() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldConnector)

};

/**
 * An entity of a road/link.
 */
class FWorldRoadLink : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldRoadLink>;
	using Super = FWorldEntityPart;

	FWorldEntityPartReference< FWorldConnector, 0 >	Predecessor;
	FWorldEntityPartReference< FWorldConnector, 0 >	Successor;

public:

	FWorldRoadLink();
	FWorldRoadLink(FWorldEntityPart* parent, const pugi::xml_node& elem);
	~FWorldRoadLink() override;

	void Resolve(FWorldEntityReferencing& referencing) override;

	WORLD_ENTITY_META_DECLARE(FWorldRoadLink)

};
